package com.polaris.live.utils.zego.core

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.StructUtils
import com.polaris.live.utils.zego.LiveEngineManage
import im.zego.minigameengine.IZegoGameActionCallback
import im.zego.minigameengine.IZegoGameEngineHandler
import im.zego.minigameengine.ZegoGameLoadState
import im.zego.minigameengine.ZegoGamePlayerState
import im.zego.minigameengine.ZegoGameRobotConfig
import im.zego.minigameengine.ZegoGameState

/**
 * GameEventHandlerHelper
 *
 * @author Created by lucas on 2024/3/24 09:01
 */
class GameEventHandlerHelper : IZegoGameEngineHandler {

    private val eventHandler = StructUtils.newSaleSet<IZegoGameEngineHandler>()

    /**
     * 观察请求，会自动取消
     */
    fun observe(owner: LifecycleOwner, handler: IZegoGameEngineHandler) {
        if (owner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            return
        }
        if (eventHandler.contains(handler)) {
            return
        }

        eventHandler.add(handler)

        owner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    eventHandler.remove(handler)
                }
            }
        })
    }

    /**
     * 添加事件监听，注意使用[removeEventHandler]取消监听
     */
    fun addEventHandler(handler: IZegoGameEngineHandler) {
        eventHandler.add(handler)
    }

    /**
     * 删除事件监听
     */
    fun removeEventHandler(handler: IZegoGameEngineHandler) {
        eventHandler.remove(handler)
    }

    // token 过期前 30s 触发回调，通常配合方法 updateToken 函数使用，回调函数无参；
    override fun onTokenWillExpire() {
        eventHandler.forEach {
            it.onTokenWillExpire()
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onTokenWillExpire"
        }
    }

    // 通知游戏加载的状态
    override fun onGameLoadStateUpdate(gameLoadState: ZegoGameLoadState?) {
        eventHandler.forEach {
            it.onGameLoadStateUpdate(gameLoadState)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "gameLoadState $gameLoadState"
        }
    }

    // 通知游戏运行状态（SDK 版本低于 1.4.0 时，推荐使用此回调）
    override fun onGameStateUpdate(gameState: ZegoGameState?) {
        //ignore
    }

    // 通知游戏运行状态（SDK 版本为 1.4.0 及以上时，推荐使用此回调）
    override fun onGameStateUpdate(gameState: ZegoGameState?, reasonCode: Int) {
        eventHandler.forEach {
            it.onGameStateUpdate(gameState, reasonCode)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameStateUpdate $gameState, reasonCode $reasonCode"
        }
    }

    // 通知当前玩家的状态（游戏中/不在游戏中）
    override fun onPlayerStateUpdate(playerState: ZegoGamePlayerState?) {
        eventHandler.forEach {
            it.onPlayerStateUpdate(playerState)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onPlayerStateUpdate $playerState"
        }
    }

    // 通知反加载游戏成功
    override fun onUnloaded(gameID: String?) {
        eventHandler.forEach {
            it.onUnloaded(gameID)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onUnloaded $gameID"
        }
    }

    // 通知玩家需要补充游戏积分才能继续玩游戏
    override fun onChargeRequire(gameID: String?) {
        eventHandler.forEach {
            it.onChargeRequire(gameID)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onChargeRequire $gameID"
        }
    }

    // 如果加载游戏时设置了自定义播放游戏声音，会收到这个回调，通知开发者需要控制声音文件的播放
    override fun onGameSoundPlay(
        name: String?,
        isPlay: Boolean,
        url: String?,
        isLoop: Boolean,
        volume: Int
    ) {
        eventHandler.forEach {
            it.onGameSoundPlay(name, isPlay, url, isLoop, volume)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameSoundPlay $name, isPlay $isPlay, url $url, isLoop $isLoop, volume $volume"
        }
    }

    // 如果加载游戏时设置了自定义播放游戏声音，此回调通知开发者需要修改 onGameSoundPlay 提及的声音的音量。
    override fun onGameSoundVolumeChange(name: String?, volume: Int) {
        eventHandler.forEach {
            it.onGameSoundVolumeChange(name, volume)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameSoundVolumeChange $name, volume $volume"
        }
    }

    // 通知游戏运行错误
    override fun onGameError(errorCode: Int, errorMessage: String?) {
        eventHandler.forEach {
            it.onGameError(errorCode, errorMessage)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameError $errorCode, errorMessage $errorMessage"
        }
    }

    // 通知游戏按钮点击事件
    override fun onActionEventUpdate(actionID: Int, data: String?) {
        eventHandler.forEach {
            it.onActionEventUpdate(actionID, data)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onActionEventUpdate $actionID, data $data"
        }
    }

    // 游戏每局结算信息，Json 格式内容
    override fun onGameResult(result: String?) {
        eventHandler.forEach {
            it.onGameResult(result)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameResult $result"
        }
    }

    // 在开始随机匹配半屏或全屏模式游戏前，如果需要配置机器人，会收到这个回调，开发者需要返回机器人的配置信息。
    override fun onRobotConfigRequire(gameID: String?): ZegoGameRobotConfig? {
        val result = eventHandler.mapNotNull {
            it.onRobotConfigRequire(gameID)
        }.firstOrNull()

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onRobotConfigRequire $gameID"
        }

        return result
    }

    // 加载游戏后，通知开发者要改变麦克风的状态。
    override fun onMicStateChange(isMute: Boolean) {
        eventHandler.forEach {
            it.onMicStateChange(isMute)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onMicStateChange $isMute"
        }
    }

    // 加载游戏后，通知开发者要改变扬声器的状态。
    override fun onSpeakerStateChange(userIDList: List<String?>?, isMute: Boolean) {
        eventHandler.forEach {
            it.onSpeakerStateChange(userIDList, isMute)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onSpeakerStateChange $userIDList, isMute $isMute"
        }
    }

    /**
     * 玩家在游戏内匹配模式游戏做动作，通过此回调通知开发者，开发者决定这个动作是否生效。
     * 允许执行，请调用 callback.onSuccess() ；
     * 不允许执行，请调用 callback.onFail(errorCode)
     *
     * actionID 举例如下：
     * 加入座位：1001
     * 离开座位：1002
     * 随机加入座位：1003
     */
    override fun onGameActionRequest(
        actionID: Int,
        data: String?,
        callback: IZegoGameActionCallback?
    ) {
        eventHandler.forEach {
            it.onGameActionRequest(actionID, data, callback)
        }

        LogExt.logI(LiveEngineManage.TAG_GAME) {
            "onGameActionRequest $actionID, data $data"
        }
    }
}

/**
 * 转发
 */
interface ForwardGameEventHandlerListener {

    /**
     * 获取代理
     */
    fun getZegoGameEngineHandler(): IZegoGameEngineHandler?

}

/**
 * 代理
 */
class DelegateGameEventHandlerHelper(
    private val onGetHandler: () -> IZegoGameEngineHandler?
) : IZegoGameEngineHandler {

    override fun onTokenWillExpire() {
        onGetHandler()?.onTokenWillExpire()
    }

    override fun onGameLoadStateUpdate(gameLoadState: ZegoGameLoadState?) {
        onGetHandler()?.onGameLoadStateUpdate(gameLoadState)
    }

    override fun onGameStateUpdate(gameLoadState: ZegoGameState?) {
        onGetHandler()?.onGameStateUpdate(gameLoadState)
    }

    override fun onGameStateUpdate(gameState: ZegoGameState?, reasonCode: Int) {
        onGetHandler()?.onGameStateUpdate(gameState, reasonCode)
    }

    override fun onPlayerStateUpdate(playerState: ZegoGamePlayerState?) {
        onGetHandler()?.onPlayerStateUpdate(playerState)
    }

    override fun onUnloaded(gameID: String?) {
        onGetHandler()?.onUnloaded(gameID)
    }

    override fun onChargeRequire(gameID: String?) {
        onGetHandler()?.onChargeRequire(gameID)
    }

    override fun onGameSoundPlay(name: String?, isPlay: Boolean, url: String?, isLoop: Boolean, volume: Int) {
        onGetHandler()?.onGameSoundPlay(name, isPlay, url, isLoop, volume)
    }

    override fun onGameSoundVolumeChange(name: String?, volume: Int) {
        onGetHandler()?.onGameSoundVolumeChange(name, volume)
    }

    override fun onGameError(errorCode: Int, errorMessage: String?) {
        onGetHandler()?.onGameError(errorCode, errorMessage)
    }

    override fun onActionEventUpdate(actionID: Int, data: String?) {
        onGetHandler()?.onActionEventUpdate(actionID, data)
    }

    override fun onGameResult(result: String?) {
        onGetHandler()?.onGameResult(result)
    }

    override fun onRobotConfigRequire(gameID: String?): ZegoGameRobotConfig? {
        return onGetHandler()?.onRobotConfigRequire(gameID)
    }

    override fun onMicStateChange(isMute: Boolean) {
        onGetHandler()?.onMicStateChange(isMute)
    }

    override fun onSpeakerStateChange(userIDList: List<String?>?, isMute: Boolean) {
        onGetHandler()?.onSpeakerStateChange(userIDList, isMute)
    }

    override fun onGameActionRequest(actionID: Int, data: String?, callback: IZegoGameActionCallback?) {
        onGetHandler()?.onGameActionRequest(actionID, data, callback)
    }
}